package com.ihg.hiex.admin.web.controller.session.preparation;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.ihg.hiex.admin.entity.security.Login;
import com.ihg.hiex.admin.service.account.AssessorService;
import com.ihg.hiex.admin.service.account.DelegateService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.participator.SessionParticipator;
import com.ihg.hiex.entity.session.task.SessionTask;
import com.ihg.hiex.entity.user.Assessor;
import com.ihg.hiex.entity.user.Delegate;

/**
 * 
 * @author Sanz
 *
 */
@Controller
@RequestMapping("/sessions/{sessionId}/schedulings")
@MenuSetting("menu-sessions")
public class SchedulingController {
    
    private final static Logger logger = LoggerFactory.getLogger(SchedulingController.class);
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private AssessorService assessorService;
    
    @Autowired
    private DelegateService delegateService;
    
    /**
     * assessor-delegate relation and group
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @MenuSetting(value = "submenu-preparation-scheduling")
    @RequestMapping(path = "/relation", method = RequestMethod.GET)
    public ModelAndView relation(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-relation");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // 1. load 'Scheduling Relation' session task
        SessionTask relationTask = sessionService.loadSessionTask(session, "Scheduling Relation");
        modelAndView.addObject("relationTask", relationTask);
        
        // 2. list subSessionA's all participators
        Map<String, List<SessionParticipator>> subSessionA = sessionService.listParticipator(session, "A");
        modelAndView.addObject("subSessionA", subSessionA);
        
        // 3. list subSessionB's all participators
        Map<String, List<SessionParticipator>> subSessionB = sessionService.listParticipator(session, "B");
        modelAndView.addObject("subSessionB", subSessionB);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param group
     * @return
     */
    @MenuSetting(value = "submenu-preparation-scheduling")
    @RequestMapping(path = "/schedule", method = RequestMethod.GET)
    public ModelAndView schedule(@Secure Login login,
                                 @PathVariable("sessionId") Long sessionId,
                                 @RequestParam(name = "group", required = false) String group) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-schedule");
        
        // 1. load session
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // 2. load scheduling relation task
        SessionTask task = sessionService.loadSessionTask(session, "Scheduling Relation");
        modelAndView.addObject("task", task);
        
        // 3.1 list subSessionA's all participators
        Map<String, List<SessionParticipator>> subSessionA = sessionService.listSortParticipator(session, "A");
        modelAndView.addObject("subSessionA", subSessionA);
        
        // 3.2 list subSessionB's all participators
        Map<String, List<SessionParticipator>> subSessionB = sessionService.listSortParticipator(session, "B");
        modelAndView.addObject("subSessionB", subSessionB);
        
        // 若group为null，默认显示subSessionA的第一个group
        if(StringUtils.isEmpty(group)) {
            Iterator<Entry<String, List<SessionParticipator>>> iter = subSessionA.entrySet().iterator();
            while(iter.hasNext()){
                group = iter.next().getKey();
                break;
            }
        }
        
        modelAndView.addObject("subGroup", group);
        String subSession = subSessionA.containsKey(group) ? "A" : "B";
        modelAndView.addObject("subSession", subSession);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/relation/sub-session", method = RequestMethod.GET)
    public ModelAndView changeSubSession(@PathVariable("sessionId") Long sessionId) {

        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-sub-session");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // list subSessionA's all participators
        Map<String, List<SessionParticipator>> subSessionA = sessionService.listParticipator(session, "A");
        modelAndView.addObject("subSessionA", subSessionA);
        
        // list subSessionB's all participators
        Map<String, List<SessionParticipator>> subSessionB = sessionService.listParticipator(session, "B");
        modelAndView.addObject("subSessionB", subSessionB);

        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param subSessionA
     * @param subSessionB
     * @return
     */
    @RequestMapping(value = "/relation/sub-session", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody String onChangeSubSession(@PathVariable("sessionId") Long sessionId,
                                                   @RequestParam("subSessionA") String subSessionA,
                                                   @RequestParam("subSessionB") String subSessionB) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            sessionService.changeSubSession(session, subSessionA, subSessionB);
            
            httpResult.success().message("Successed");
            
        } catch (Exception e) {
            logger.error("onChangeSubSession - ", e);
            httpResult.fail("500").message("Failed");
        }

        return JsonUtils.toJson(httpResult);
    }
    
    /**
     * add assessor
     * 
     * @param sessionId
     * @param subSession
     * @param subGroup
     * @param seat
     * @return
     */
    @RequestMapping(value = "/relation/assessors/add", method = RequestMethod.GET)
    public ModelAndView assessorAdd(@PathVariable("sessionId") Long sessionId,
                                    @RequestParam("subSession") String subSession,
                                    @RequestParam("subGroup") String subGroup,
                                    @RequestParam("seat") String seat) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-add-assessor");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("subSession", subSession);
        modelAndView.addObject("subGroup", subGroup);
        modelAndView.addObject("seat", seat);
        
        List<Assessor> assessors = assessorService.listAssessor(sessionId);
        modelAndView.addObject("assessors", assessors);
        
        return modelAndView;
        
    }
    
    /**
     * on add assessor
     * 
     * @param sessionId
     * @param subSession
     * @param subGroup
     * @param seat
     * @param assessor
     * @return
     */
    @RequestMapping(value = "/relation/assessors", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onAssessorAdd(@PathVariable("sessionId") Long sessionId,
                                                  @RequestParam("subSession") String subSession,
                                                  @RequestParam("subGroup") String subGroup,
                                                  @RequestParam("seat") String seat,
//                                                  Assessor assessor,
                                                  @RequestParam("assessorId") Long assessorId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            Assessor assessor = assessorService.load(Assessor.class, assessorId);
            
            // 计算after seat
            Integer afterSeat = Integer.parseInt(seat) + 1;
            
            sessionService.addAssessor(session, assessor, subSession, subGroup, new String[]{seat, afterSeat.toString()});
            
            httpResult.success().message("添加成功");
            
        } catch (Exception e) {
            logger.error("onAssessorAdd - ", e);
            httpResult.fail("500").message("添加失败");
        }
        
        return httpResult;
    }
    
    /**
     * remove assessor panel
     * 
     * @param sessionId
     * @param assessorId
     * @return
     */
    @RequestMapping(value = "/relation/assessors/{assessorId}/remove", method = RequestMethod.GET)
    public ModelAndView assessorRemove(@PathVariable("sessionId") Long sessionId, @PathVariable("assessorId") Long assessorId) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-remove-assessor");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("assessorId", assessorId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param assessorId
     * @return
     */
    @RequestMapping(value = "/relation/assessors/{assessorId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onAssessorRemove(@PathVariable("sessionId") Long sessionId, @PathVariable("assessorId") Long assessorId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            sessionService.assessorRemove(session, assessorId);
            
            httpResult.success().message("删除成功");
            
        } catch (Exception e) {
            logger.error("onAssessorRemove - ", e);
            httpResult.fail("500").message("删除失败");
        }
        
        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param subSession
     * @param subGroup
     * @param assessorId
     * @param seat
     * @return
     */
    @RequestMapping(value = "/relation/delegates/add", method = RequestMethod.GET)
    public ModelAndView delegateAdd(@PathVariable("sessionId") Long sessionId,
                                    @RequestParam("subSession") String subSession,
                                    @RequestParam("subGroup") String subGroup,
                                    @RequestParam("assessorId") Long assessorId,
                                    @RequestParam("seat") String seat) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-add-delegate");

        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        Assessor assessor = assessorService.load(Assessor.class, assessorId);
        List<Delegate> delegates = sessionService.listDelegate(session, assessor);
        modelAndView.addObject("delegates", delegates);
        
        modelAndView.addObject("subSession", subSession);
        modelAndView.addObject("subGroup", subGroup);
        modelAndView.addObject("seat", seat);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param subSession
     * @param subGroup
     * @param seat
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/relation/delegates", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDelegateAdd(@PathVariable("sessionId") Long sessionId,
                                                  @RequestParam("subSession") String subSession,
                                                  @RequestParam("subGroup") String subGroup,
                                                  @RequestParam("seat") String seat,
                                                  @RequestParam("delegateId") Long delegateId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            Delegate delegate = delegateService.load(Delegate.class, delegateId);
            
            sessionService.addDelegate(session, delegate, subSession, subGroup, seat);
            
            httpResult.success().message("添加成功");
            
        } catch (Exception e) {
            logger.error("onDelegateAdd - ", e);
            httpResult.fail("500").message("添加失败");
        }
        
        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/relation/delegates/{delegateId}/remove", method = RequestMethod.GET)
    public ModelAndView delegateRemove(@PathVariable("sessionId") Long sessionId,
                                       @PathVariable("delegateId") Long delegateId) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-remove-delegate");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("delegateId", delegateId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/relation/delegates/{delegateId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDelegateRemove(@PathVariable("sessionId") Long sessionId,
                                                     @PathVariable("delegateId") Long delegateId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            sessionService.delegateRemove(session, delegateId);
            
            httpResult.success().message("删除成功");
            
        } catch (Exception e) {
            logger.error("onDelegateRemove - ", e);
            httpResult.fail("500").message("删除失败");
        }
        
        return httpResult;
    }
    
    /**
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/schedule/confirm", method = RequestMethod.GET)
    public ModelAndView scheduleConfirm(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/preparation/scheduling/scheduling-confirm");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/schedule/confirm", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onScheduleConfirm(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            SessionTask task = sessionService.loadSessionTask(session, "Scheduling Relation");
            
            sessionService.confirm(session, task, login.getId(), login.getName());
            
            httpResult.success().message("确认成功");
            
        } catch (Exception e) {
            logger.error("onScheduleConfirm - ", e);
            httpResult.fail("500").message("确认失败");
        }
        
        return httpResult;
        
    }
    
}
